package com.cin.cma.server.pos.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.filter.PropertyFilter;
import com.cin.cma.common.constant.MsgTypeConstant;
import com.cin.cma.common.enums.JyServerErrorCode;
import com.cin.cma.common.enums.SystemErrorCode;
import com.cin.cma.common.exception.UserFriendlyException;
import com.cin.cma.common.model.SocketRequest;
import com.cin.cma.common.model.SocketResponse;
import com.cin.cma.common.model.finixx.base.BaseRequest;
import com.cin.cma.common.model.finixx.base.BaseResponse;
import com.cin.cma.common.model.finixx.response.BookingOrderResponse;
import com.cin.cma.server.pos.common.extension.ActionExtension;
import com.cin.cma.server.pos.common.extension.ErrorValid;
import com.cin.cma.server.pos.common.extension.EventConvert;
import com.cin.cma.server.pos.common.extension.Signuature;
import com.cin.cma.server.pos.config.SocketIOService;
import com.cin.cma.server.pos.model.socket.SocketBody;
import com.cin.cma.server.pos.service.IProxyRequestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 *
 * @Date：2024-07-17 12:08
 */
@Slf4j
@Service
public class ProxyRequestServiceImpl implements IProxyRequestService {
    @Autowired
    private SocketIOService socketIoService;
    @Autowired
    private ErrorValid errorValid;

    @Override
    public <T extends BaseRequest, X extends BaseResponse> X context(String proxyPostUrl, Integer timeout, T request, Class<X> clazz, ActionExtension func) throws Exception {
        if (timeout == null) {
            timeout = 15;
        }
        int loopTimes = timeout * 1000 / 30;
        String requestId = request.getSerialNumber();
        if (StrUtil.isBlank(requestId)) {
            requestId = IdUtil.fastSimpleUUID();
            request.setSerialNumber(requestId);
        }
        if (StrUtil.isBlank(request.getVersion())) {
            request.setVersion("1.0.0.1");
        }
        try {
            request.setSignature(Signuature.get(request));
            PropertyFilter filter = (s, name, v) -> !"appKey".equals(name);
            String message = JSON.toJSONString(request, filter);
            SocketRequest socketRequest = new SocketRequest();
            socketRequest.setRequestUrl(proxyPostUrl);
            socketRequest.setRequestId(requestId);
            socketRequest.setRequestBody(message);
            socketRequest.setMessageType(MsgTypeConstant.SYNC);
            this.socketIoService.sendMessage(socketRequest, request.getLocationCd(), EventConvert.toEvent(request.getCode()));
            for (int i = 0; i < loopTimes; i++) {
                ThreadUtil.sleep(30);
                if (SocketIOService.response.get(requestId) != null) {
                    SocketResponse socketResponse = SocketIOService.response.get(requestId).getResposne();
                    if (socketResponse != null) {
                        if (socketResponse.getHttpStatus() != 200) {
                            throw new UserFriendlyException(SystemErrorCode.NETWORK_ERROR, "JYLOCAL_STATUS=" + socketResponse.getHttpStatus());
                        }
                        X response = JSON.parseObject(socketResponse.getResponseBody(), clazz);
                        if (response instanceof BookingOrderResponse) {
                            BookingOrderResponse bookingOrderResponse = (BookingOrderResponse) response;
                            //卖品错误异常捕抓
                            if (bookingOrderResponse.getResult() != 0 && bookingOrderResponse.getPosSaleResult() != null) {
                                throw new UserFriendlyException(JyServerErrorCode.EXCEPTION, bookingOrderResponse.getResult() + "-" + bookingOrderResponse.getPosSaleResult().getErrMessage());
                            }
                        }
                        this.errorValid.result(response, func);
                        return response;
                    }
                }
            }
        } catch (Exception e) {
            log.error("socket error requestId={}", requestId, e);
            throw e;
        } finally {
            SocketBody socketBody = SocketIOService.response.get(requestId);
            if (socketBody != null) {
                log.info(socketBody.toString());
            }
            SocketIOService.response.remove(requestId);
        }
        throw new UserFriendlyException(SystemErrorCode.NETWORK_TIMEOUT, "SOCKET_RESULT_TIMEOUT");
    }

    @Override
    public <T extends BaseRequest, X extends BaseResponse> X context(Integer timeout, T request, Class<X> clazz, ActionExtension func) throws Exception {
        return this.context(null, timeout, request, clazz, func);
    }

    @Override
    public <T extends BaseRequest, X extends BaseResponse> X context(Integer timeout, T request, Class<X> clazz) throws Exception {
        return this.context(timeout, request, clazz, null);
    }

    @Override
    public <T extends BaseRequest, X extends BaseResponse> X context(T request, Class<X> clazz, ActionExtension func) throws Exception {
        return this.context(null, request, clazz, func);
    }

    @Override
    public <T extends BaseRequest, X extends BaseResponse> X context(T request, Class<X> clazz) throws Exception {
        return this.context(null, request, clazz);
    }

}
